// backend/log_consumer.go
package main

import (
	"fmt"
	"time"

	"github.com/go-xorm/xorm"
)

// StartLogConsumer 启动日志消费者（解析+批量写入数据库）
// 参数：engine XORM引擎，logChan 日志通道（从通道读取日志）
func StartLogConsumer(engine *xorm.Engine, logChan <-chan TrafficLog) {
	var logBatch []TrafficLog // 批量日志缓存

	// 定时刷新批次（即使未达批量大小，1秒内也会写入）
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	for {
		select {
		/*
				log, ok := <-logChan：
			从通道读数据的 “完整语法”：log 是读取到的日志（TrafficLog 类型），ok 是布尔值 ——ok=true 表示通道正常且有数据，ok=false 表示通道已被生成者关闭（没有更多数据了）。
			注意：如果通道关闭且无数据，直接 log := <-logChan 会读取到 TrafficLog 的 “零值”（而非报错），因此必须用 ok 判断通道状态，避免处理无效数据。
			if !ok { ... }：通道关闭后的 “收尾逻辑”：
			先检查缓存是否有剩余日志（len(logBatch) > 0），如果有则批量插入 —— 这是 “数据不丢失” 的关键，避免通道关闭时缓存中的日志被丢弃。
			return 退出函数：通道关闭后，没有新日志了，消费者可以停止，结束循环。
			logBatch = append(logBatch, log)：
			切片的 “动态追加” 语法：将新日志 log 加入缓存 logBatch，切片长度自动 + 1。
			底层原理：如果切片容量足够，直接追加；容量不足，会自动扩容（分配更大的内存，复制旧数据）——XORM 批量插入时会处理切片扩容后的所有数据，无需手动管理容量。
			if len(logBatch) >= Config.BatchSize { ... }：
			达到批量大小（如 100 条）时，调用 batchInsertLogs 写入数据库，然后清空缓存（logBatch = []TrafficLog{}）。
			为什么要清空？清空后切片长度归 0，下次可以重新追加新日志 —— 如果不清空，切片会一直累积，导致内存占用越来越大。
		*/
		case log, ok := <-logChan:
			if !ok {
				// 日志通道已关闭，处理剩余缓存日志
				if len(logBatch) > 0 {
					batchInsertLogs(engine, logBatch)
				}
				fmt.Println("日志通道关闭，消费者停止")
				return
			}

			// 加入批量缓存
			logBatch = append(logBatch, log)

			// 达到批量大小，执行插入
			if len(logBatch) >= Config.BatchSize {
				batchInsertLogs(engine, logBatch)
				logBatch = []TrafficLog{} // 清空缓存
			}

		case <-ticker.C:
			// 定时插入（避免缓存中日志长时间未写入）
			if len(logBatch) > 0 {
				batchInsertLogs(engine, logBatch)
				logBatch = []TrafficLog{}
			}
		}
	}
}

// batchInsertLogs 批量插入日志到数据库
func batchInsertLogs(engine *xorm.Engine, logs []TrafficLog) {
	start := time.Now()
	_, err := engine.Insert(&logs)
	if err != nil {
		fmt.Printf("批量插入日志失败（%d条）: %v\n", len(logs), err)
		return
	}
	fmt.Printf("批量插入日志成功，%d条，耗时%v\n", len(logs), time.Since(start))
}
